package org.compiere.process;

import java.math.BigDecimal;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.TimeZone;
import org.adempiere.exceptions.AdempiereException;
import org.compiere.model.MBPartner;
import org.compiere.model.Mhrmattendance;
import org.compiere.model.Mhrmorder;
import org.compiere.model.Mhrmovertime;
import org.compiere.model.Mhrmovertimeline;
import org.compiere.model.Mhrmsalaryemployee;
import org.compiere.model.Mhrmsheduleemployee;
import org.compiere.model.Mhrmworktime;
import org.compiere.model.X_C_Period;
import org.compiere.util.Env;
import org.compiere.util.Msg;
import org.eevolution.model.X_HR_Employee;
import extend.org.compiere.hrm.AverageSalary;
import extend.org.compiere.hrm.TaxVariable;

public class GenerateOvertimeSalary extends SvrProcess {
	
	/**	Employee List	*/
	private MBPartner[] m_lines;
		
	/** Attendance */
	private Mhrmattendance[] overtimetype = null;
	
	/** Overtime */
	private Mhrmovertime overtime = null;
	private Mhrmovertimeline overtimeline = null;
	
	/** Tax */
	private TaxVariable taxcomp = null;
	
	/** Average */
	private AverageSalary average = null;
	
	/** Other variables */
	private int C_BPartner_ID = 0;
	private int HR_Block_ID  = 0;
	private int HR_Department_ID  = 0;
	X_HR_Employee he = null;
	Timestamp dateFrom = null;
	Calendar calendar1 = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
	Calendar calendar2 = Calendar.getInstance(TimeZone.getTimeZone("GMT"));	
	
	long Night22  =  57600000;
	long nNight22 = -28800000;
	long Night23  =  61200000;
	long nNight23 = -25200000;
	long Day21    =  54000000;
	
			
	long zero    = 0;	
	long millis3 = 0;
	
	

	@Override
	protected void prepare() {
		overtime = new Mhrmovertime(getCtx(), getRecord_ID(), null);

	}

	@Override
	protected String doIt() throws Exception {
		C_BPartner_ID = overtime.getC_BPartner_ID();
		HR_Block_ID = overtime.getHR_Block_ID();
		HR_Department_ID = overtime.getHR_Department_ID();
		X_C_Period Period = new X_C_Period(getCtx(), overtime.getC_Period_ID(), null);
		dateFrom = Period.getEndDate();
		
		MBPartner bp = new MBPartner(getCtx(), overtime.getC_BPartner_ID(), null);
		m_lines = bp.getPartnerEmployeeDate(C_BPartner_ID, HR_Block_ID, HR_Department_ID, dateFrom, true);
		
		for(MBPartner b: m_lines){
			 he = X_HR_Employee.getHR_Employee(b.getC_BPartner_ID(),true);
			   if (he.getC_BPartner_ID() == 0)
					throw new AdempiereException ("Info about employee was empty");
			   
			   overtimetype = Mhrmattendance.getAttendanceType(b.getC_BPartner_ID(), Period.getStartDate(), Period.getEndDate(), overtime.gethrm_ordertype());
			   for (Mhrmattendance m: overtimetype){
				   
				    double dayhour    = 0;
					double nighthour  = 0;
					double daytotal   = 0;
					double nighttotal = 0;
					double total      = 0;
				   				
				   overtimeline = Mhrmovertimeline.getOvertimeRec(b.getC_BPartner_ID(), m.gethrm_order_ID(), m.getStartDate());
				   if (overtimeline == null || overtimeline.get_ID() == 0)
					   overtimeline = new Mhrmovertimeline(getCtx(), 0, null);				  
				   overtimeline.sethrm_overtime_ID(overtime.gethrm_overtime_ID());
				   overtimeline.setC_BPartner_ID(b.getC_BPartner_ID());
				   overtimeline.setHR_Department_ID(he.getHR_Department_ID());
				   overtimeline.setHR_Job_ID(he.getHR_Job_ID());
				   overtimeline.setDateFrom(m.getStartDate());
				   overtimeline.sethrm_order_ID(m.gethrm_order_ID());
				   
				   /** Take amount */
				   BigDecimal amount = Mhrmsalaryemployee.getAmountSalary(b.getC_BPartner_ID(), dateFrom);
				   if (amount == null)
					   throw new AdempiereException (" Amount for this person was empty: " + b.getName() + " (" + b.getC_BPartner_ID() + ")," + dateFrom + " ");		   
				   overtimeline.sethrm_amountsalary(amount);
				   
				   /** Define work hours */
				   int shedulerule_id = Mhrmsheduleemployee.getSheduleRule(b.getC_BPartner_ID(), dateFrom);
				   int workhours = Mhrmworktime.getWorkHours(shedulerule_id, dateFrom);
				   overtimeline.sethrm_hourquota(new BigDecimal(workhours));
				   
				   double nighttariff = (amount.doubleValue()/workhours) * 1.5;
				   double daytariff = amount.doubleValue()/workhours;
				   
				   /** Take times */
				   Mhrmorder order = Mhrmorder.getOrderRec(m.gethrm_order_ID(), m.getStartDate(), m.getEndDate(), overtime.gethrm_ordertype());
				   if (order == null || order.get_ID() == 0)
					   throw new AdempiereException (" Info abount overtime for this order incorrect:" + m.gethrm_order_ID() + " ");
				   overtimeline.setStartTime(order.getStartTime());
				   overtimeline.setEndTime(order.getEndTime());
				   
				   //				  
				   long millis1 = order.getStartTime().getTime();				   		   
				   long millis2 = order.getEndTime().getTime();		   
							   				   
				   /** Convert 22 hour to negative */
				   if (millis1 >= Night22 && millis1 < Night23)
					   millis1 = nNight22;
				   if (millis2 >= Night22 && millis2 < Night23)
					   millis2 = nNight22;
				   
				   /** Convert 23 hour to negative */
				   if (millis1 >= Night23)
					   millis1 = nNight23;
				   if (millis2 >= Night23)
					   millis2 = nNight23;				   
				   
				   if (millis1 > zero && millis1 < Night22){
					   if (millis2 > zero && millis2 < millis1){
						   millis3 = Math.abs(Night22 - millis1);
						   dayhour = millis3 / (60 * 60 * 1000) + millis2 / (60 * 60 * 1000);
						   nighthour = Math.abs(nNight22) / (60 * 60 * 1000);						   
					   }else{
						   nighthour = 0;
						   millis3 = Math.abs(millis2 - millis1);
						   dayhour = millis3 / (60 * 60 * 1000);
					   }
				   }else if (millis1 <= zero){ 
					   if (millis2 <= zero){ 
						   millis3 = Math.abs(millis1 - millis2);
						   nighthour = millis3 / (60 * 60 * 1000);
						   dayhour = 0;
					   }else{ 
						  nighthour = Math.abs(millis1 / (60 * 60 * 1000));
						  dayhour = millis2 / (60 * 60 * 1000);
					   }
				   }else{  
					   if (millis2 <= zero){ 
						   dayhour = Math.abs(Day21 - millis1) / (60 * 60 * 1000);						  
						   nighthour = Math.abs(Night23 - millis2) / (60 * 60 * 1000);						   
					   }else{ 
						   nighthour = 0;
						   millis3 = Math.abs(millis2 - millis1);
						   dayhour = millis3 / (60 * 60 * 1000);
					   }
				   }
				   
				   /** Define night hours salary */
				   overtimeline.sethrm_nighthours(new BigDecimal(nighthour));					  
				   overtimeline.sethrm_nighttariff(new BigDecimal(nighttariff));
				   //
				   nighttotal = nighthour * nighttariff;
				   overtimeline.sethrm_nighttotal(new BigDecimal(nighttotal));					   
			  
				   /** Define day hours salary */
				   overtimeline.sethrm_dayhours(new BigDecimal(dayhour));					   				   
				   overtimeline.sethrm_daytariff(new BigDecimal(daytariff));
				   //
				   daytotal = dayhour * daytariff;
				   overtimeline.sethrm_daytotal(new BigDecimal(daytotal));	
				   
				   /** Calculate total */
				   total = daytotal + nighttotal;
				   overtimeline.sethrm_total(new BigDecimal(total));
				   
				   overtimeline.sethrm_days(0);				   
				   overtimeline.saveEx();
			   }	   
			   
		}		
		
		return Msg.translate(Env.getCtx(), "Success");
	}

}
